package com.example.demo.security.jwt;

import com.example.demo.model.User;
import com.example.demo.security.UserDetailsImpl;
import com.example.demo.service.UserService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;


/**
 * 验证用户名密码正确后，生成一个token，并将token返回给客户端
 * 该类继承自UsernamePasswordAuthenticationFilter，重写了其中的2个方法
 * attemptAuthentication ：接收并解析用户凭证。
 * successfulAuthentication ：用户成功登录后，这个方法会被调用，我们在这个方法里生成token。
 */
public class JWTLoginFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;
    private Logger logger= LoggerFactory.getLogger(JWTLoginFilter.class);


    private JWTUtils jwtUtils=new JWTUtils();
    @Autowired
    private UserService userService;



    public JWTLoginFilter(AuthenticationManager authenticationManager) {
        //super.setFilterProcessesUrl("/login");

        this.authenticationManager = authenticationManager;

    }

    // 接收并解析用户凭证
    @Override
    public Authentication attemptAuthentication(HttpServletRequest req,
                                                HttpServletResponse res) throws AuthenticationException {


        if (req.getContentType() == null) {
            throw new AuthenticationServiceException("请求头类型不支持: " + req.getContentType());
        }

        User user=null;
        try {
            ObjectMapper objectMapper=new ObjectMapper();
            user= objectMapper.readValue(req.getInputStream(), User.class);
            logger.info("qstr:"+user.getUsername());
        } catch (IOException e) {
            e.printStackTrace();
        }
        /*String account =obtainUsername(req);
        String password=obtainPassword(req);
        logger.info("user: "+account+" attempt login");
        logger.info("content type "+req.getContentType());
        logger.info("request url "+ req.getRequestURI());
        logger.info("test header :"+req.getHeader("test"));*/


        logger.info("user:"+user.getUsername()+" attempt login");

//        User user=userService.findUserByAccount(account);
//
//        logger.info("username is "+user.getUsername());
//        for(GrantedAuthority authority :user.getAuthorities())
//        {
//            logger.info("authority: "+authority.getAuthority());
//        }

        return authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(
                        user.getUsername(),
                        user.getPassword(),
                        new ArrayList<>())
        );

    }


    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse res, AuthenticationException failed) throws IOException, ServletException {
        super.unsuccessfulAuthentication(request, res, failed);

        logger.info("login failed");

        res.setContentType("application/json;charset=UTF-8");
        ObjectMapper objectMapper=new ObjectMapper();

        UserDetailsImpl user=new UserDetailsImpl();
        String value=objectMapper.writeValueAsString(user);
        res.getWriter().write(value);



    }



    // 用户成功登录后，这个方法会被调用，在这个方法里生成token
    @Override
    protected void successfulAuthentication(HttpServletRequest req,
                                            HttpServletResponse res,
                                            FilterChain chain,
                                            Authentication auth) throws IOException, ServletException {

        ObjectMapper objectMapper=new ObjectMapper();

        UserDetailsImpl user=(UserDetailsImpl) auth.getPrincipal();

        StringBuilder roles=new StringBuilder();

        for(GrantedAuthority authority : user.getAuthorities())
        {
            roles.append(authority.getAuthority()+" ");
            logger.info("user authority is "+authority.getAuthority());

        }



        res.setContentType("application/json;charset=UTF-8");
        //String value=objectMapper.writerWithView(UserDetailsImpl.UserSimpleView.class).writeValueAsString(user);
        String value=objectMapper.writeValueAsString(user);

        logger.info("login sucess "+user.getUsername());

        String token=jwtUtils.createToken(user.getUsername(),roles.toString());



//        String token = Jwts.builder()
//                .setSubject(user.getUsername())
//
//                .setExpiration(new Date(System.currentTimeMillis() + 60 * 60 * 24 * 1000))
//                .signWith(SignatureAlgorithm.HS512, "lstlst")
////                .setPayload(value)
//                .compact();
//
//

        res.addHeader(jwtUtils.getHeader(),  token);
        logger.info("JWT:"+token);


        logger.info("loginResult:"+value);
        res.getWriter().write(value);

    }

}